/******************************************************************************
 * Product: Adempiere ERP & CRM Smart Business Solution                        *
 * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved.                *
 * This program is free software; you can redistribute it and/or modify it    *
 * under the terms version 2 of the GNU General Public License as published   *
 * by the Free Software Foundation. This program is distributed in the hope   *
 * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.           *
 * See the GNU General Public License for more details.                       *
 * You should have received a copy of the GNU General Public License along    *
 * with this program; if not, write to the Free Software Foundation, Inc.,    *
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.                     *
 * For the text or an alternative of this public license, you may reach us    *
 * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA        *
 * or via info@compiere.org or http://www.compiere.org/license.html           *
 *****************************************************************************/
package org.adempiere.apps.form;

import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.VetoableChangeListener;
import java.sql.*;
import java.util.*;
import java.util.List;
import java.util.logging.*;
import java.math.*;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.plaf.basic.BasicInternalFrameTitlePane.RestoreAction;
import javax.swing.table.*;

import org.adempeire.model.MBarcodeTrx;
import org.adempeire.model.MBarcodeTrxLine;
import org.adempeire.model.MLoading;
import org.adempeire.model.MLoadingLine;
import org.compiere.apps.*;
import org.compiere.apps.form.FormFrame;
import org.compiere.apps.form.FormPanel;
import org.compiere.grid.ed.*;
import org.compiere.minigrid.*;
import org.compiere.model.*;
import org.compiere.swing.*;
import org.compiere.util.*;
import org.posterita.keyname.CBPartnerKeyNamePair;

import com.jhlabs.math.SCNoise;
/**
 *  Barcode Transaction Form
 *
 *  @author  Shindu
 *  @version 1.1
 *  @since May 2013
 */


public class BarcodeTransactionIn extends CPanel
	implements FormPanel, ActionListener
{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 121224L;

	/**
	 *	Initialize Panel
	 *  @param WindowNo window
	 *  @param frame frame
	 */
	public void init (int WindowNo, FormFrame frame)
	{
		//
		Env.setContext(Env.getCtx(), WindowNo, "IsSOTrx", "N");
		log.info(frame.toString());
		p_WindowNo = WindowNo;
		m_frame = frame;
		m_frame.setMaximize(true);
		
		try
		{
			//
			MClientInfo info=MClientInfo.get(Env.getCtx());
			lenUPC=info.getUPC_Len();
			//
			dynInit();
			jbInit();			
			confirmPanel.addActionListener(this);
			confirmPanel.setOKVisible(false);
			//  Set status
			statusBar.setStatusDB("");
			//tableChanged(null);
			p_initOK = true;
		}
		catch(Exception e)
		{
			log.log(Level.SEVERE, "", e);
			p_initOK = false;
		}
		//AEnv.positionCenterWindow(Env.getWindow(p_WindowNo), this);
	}	//	init
	
	/**
	 * Get Vendor only
	 * @throws Exception
	 */
	protected void initLookup () throws Exception
	{
		//  load BPartner
		int AD_Column_ID = 3795;// 4809;        //  Vendor
		MLookup lookup = MLookupFactory.get (Env.getCtx(), p_WindowNo, 0, AD_Column_ID, DisplayType.Search);
		bPartnerField = new VLookup ("C_BPartner_ID", true, false, true, lookup);
		//load doc type
		AD_Column_ID=3792;
		lookup = MLookupFactory.get(Env.getCtx(), p_WindowNo, 0, AD_Column_ID, DisplayType.Table);
		docTypeField=new VLookup("C_DocType_ID", true, false, true, lookup);
		//Locator		
		MLocatorLookup locator = new MLocatorLookup(Env.getCtx(), p_WindowNo);
		locatorField = new VLocator ("M_Locator_ID", true, false, true,	locator, p_WindowNo);		
		int M_Warehouse_ID = Env.getContextAsInt(Env.getCtx(), "M_Warehouse_ID");		
		locatorField.setValue(MWarehouse.get(Env.getCtx(), M_Warehouse_ID).getDefaultLocator().getM_Locator_ID());
		//
				
	}   //  initBPartner
	
	/** Window No               */
	int      p_WindowNo;
	FormFrame 	m_frame;
	/** Model Tab               */
	//protected GridTab         		p_mTab;

	boolean p_initOK = false;
	boolean	isSOTrx=false;
	int totalLines;
	int lenUPC;
	int C_Uom_ID;
	String UOM;

	/** Loaded Order            */
	/**	Logger			*/
	CLogger 		log = CLogger.getCLogger(getClass());
	/**	Static Logger	*/
	//
	private CPanel parameterPanel = new CPanel();
	private BorderLayout parameterLayout = new BorderLayout();
	private CPanel parameterStdPanel = new CPanel();	
	private GridBagLayout parameterStdLayout = new GridBagLayout();
	private JScrollPane dataPane = new JScrollPane();
	private CPanel southPanel = new CPanel();
	private BorderLayout southLayout = new BorderLayout();
	private ConfirmPanel confirmPanel = new ConfirmPanel(true);
	private StatusBar statusBar = new StatusBar();
	//
	private MiniTable dataTable = new MiniTable();
	//
	private JLabel bPartnerLabel = new JLabel();	
	private VLookup bPartnerField;
	private JLabel locatorLabel = new JLabel();
	private VLocator locatorField;
	private JLabel docTypeLabel = new JLabel();
	private VLookup docTypeField; 
	private JLabel barcodeLabel = new JLabel();
	private CTextField barcodePN = new CTextField();
	private JLabel infoInserted = new JLabel();
	//
	private VCheckBox isEceran = new VCheckBox();
	private VCheckBox isGenerated = new VCheckBox();
	
	public static final String SELECT_ALL = "SelectAll";
	
	Vector<Vector<Object>> data = new Vector<Vector<Object>>();
	//objmodel
	MBarcodeTrx barcodetrx;
	
	//MInOut iohdr;
    
	/**
	 *  Static Init
	 *  @throws Exception
	 */
	private void jbInit() throws Exception
	{
		Font boldFont = new Font(getFont().getName(), Font.BOLD, 12);
		parameterPanel.setLayout(parameterLayout);
		parameterStdPanel.setLayout(parameterStdLayout);
		//
		locatorLabel.setText(Msg.translate(Env.getCtx(), "M_Locator_ID"));
		bPartnerLabel.setText(Msg.translate(Env.getCtx(), "C_BPartner_ID"));
		docTypeLabel.setText(Msg.translate(Env.getCtx(), "C_DocType_ID"));
        //
        isGenerated.setText(Msg.translate(Env.getCtx(), "IsGeneratedInOut"));
        isGenerated.setReadWrite(false);
        isEceran.setText(Msg.translate(Env.getCtx(), "IsEceran"));
        isEceran.setReadWrite(false);
        //
        barcodeLabel.setText("SCAN BARCODE");
        barcodeLabel.setFont(boldFont);
        barcodeLabel.setForeground(Color.BLUE);
        barcodePN.setFont(boldFont);
        barcodePN.setForeground(Color.BLUE);
        //
        infoInserted.setForeground(Color.BLUE);
        //
        resetValue();
		//
		m_frame.getContentPane().add(parameterPanel, BorderLayout.NORTH);
		
		parameterPanel.add(parameterStdPanel, BorderLayout.CENTER);
		//Locator
        parameterStdPanel.add(locatorLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
                ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 0, 5, 5), 0, 0));        
                    m_frame.getContentPane().add(dataPane, BorderLayout.CENTER);
        parameterStdPanel.add(locatorField, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0
               ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 5, 5), 0, 0));        
                    m_frame.getContentPane().add(dataPane, BorderLayout.CENTER);
        //Bpartner
       parameterStdPanel.add(bPartnerLabel, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0
                			,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
       parameterStdPanel.add(bPartnerField, new GridBagConstraints(3, 0, 1, 1, 0.0, 0.0
                				,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 5, 5), 0, 0));
        //Doc type
       
       parameterStdPanel.add(docTypeLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0
   			,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
       parameterStdPanel.add(docTypeField, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0
   				,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 5, 5), 0, 0));
		//Eceran
        parameterStdPanel.add(isEceran,  new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0
    			,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 5, 5), 0, 0));
		//
        parameterStdPanel.add(barcodeLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0
            ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 0, 5, 5), 0, 0));        
            	m_frame.getContentPane().add(dataPane, BorderLayout.CENTER);                    
        parameterStdPanel.add(barcodePN, new GridBagConstraints(1, 3, 1, 1, 0.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 5, 5), 0, 0));        
            	m_frame.getContentPane().add(dataPane, BorderLayout.CENTER);          	
        parameterStdPanel.add(infoInserted, new GridBagConstraints(2, 3, 1, 1, 0.0, 0.0
             ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 5, 5), 0, 0));        
              	m_frame.getContentPane().add(dataPane, BorderLayout.CENTER);
        //
                    
		dataPane.getViewport().add(dataTable, null);
		
		//
 		//
		// @Trifon
		AppsAction selectAllAction = new AppsAction (SELECT_ALL, KeyStroke.getKeyStroke(KeyEvent.VK_A, java.awt.event.InputEvent.ALT_MASK), null);
		
		CButton selectAllButton = (CButton)selectAllAction.getButton();
		selectAllButton.setMargin(new Insets (0, 10, 0, 10));
		selectAllButton.setDefaultCapable(true);
		selectAllButton.addActionListener(this);
//		confirmPanel.addButton(selectAllButton);
		//
		barcodePN.setActionCommand("Barcode");
		barcodePN.addActionListener(this);
		//
		m_frame.getContentPane().add(southPanel, BorderLayout.SOUTH);
		southPanel.setLayout(southLayout);
		southPanel.add(confirmPanel, BorderLayout.CENTER);
		m_frame.getContentPane().add(southPanel, BorderLayout.SOUTH);
		southPanel.setLayout(southLayout);
		southPanel.add(confirmPanel, BorderLayout.CENTER);
		southPanel.add(statusBar, BorderLayout.SOUTH);	   
	}   //  jbInit

	/**
	 * 	Dispose
	 */
	public void dispose()
	{
		if (m_frame != null)
			m_frame.dispose();
		m_frame = null;
	}	//	dispose

	/**
	 *  Dynamic Init (prepare dynamic fields)
	 *  @throws Exception if Lookups cannot be initialized
	 */
	private void dynInit() throws Exception
	{
		
		log.config("");
		//  load Locator
		
		initLookup();
		locatorField.setMandatory(true);
		bPartnerField.setMandatory(true);
		docTypeField.setMandatory(true);
	
		//  Translation
		statusBar.setStatusLine("Ready");
		statusBar.setStatusDB("-");

	}   //  dynInit

	
	
	/**************************************************************************
	 *  Action Listener.
	 *  @param e event
	 */
	public void actionPerformed(ActionEvent e)
	{
		boolean isError=false;
		if (e.getSource().equals(barcodePN)){
			infoInserted.setText("");
			if (barcodePN.getValue().toString().length()!=lenUPC+1){
				ADialog.error(p_WindowNo, this, "Barcode invalid format!");
				barcodePN.requestFocus();
				isError=true;			
			}else if(locatorField.getValue()==null){
				ADialog.error(p_WindowNo, this, "Locator is mandatory!");
				locatorField.requestFocus();
				isError=true;		
			}else if (bPartnerField.getValue()==null){
				ADialog.error(p_WindowNo, this, "Business partner is mandatory!");
				bPartnerField.requestFocus();
				isError=true;
			}else if (docTypeField.getValue()==null){
					ADialog.warn(p_WindowNo, this,"", "Document type is mandatory!");
					docTypeField.requestFocus();
					isError=true;
				}
			if (!isError){
				String trxName=Trx.createTrxName();
				String msg = addBarcodeLine(trxName);
				if (msg.equals("")){
					Trx.get(trxName, false).commit();
					statusBar.setStatusLine("Total lines: " + totalLines);				
				}else{
					Trx.get(trxName, false).rollback();
					ADialog.error(p_WindowNo, this, msg);
					statusBar.setStatusLine(msg);
				}
				barcodePN.requestFocus();				
			}
			barcodePN.setText("");
		}else if(e.getActionCommand().equals(ConfirmPanel.A_OK)){
			//
			if (!ADialog.ask(p_WindowNo, this,"SaveChanges?" )){
				return;
			}
			if (barcodetrx!=null){
				MInOut result=barcodetrx.generateMInOut();
				if (result!=null){
					ADialog.info(p_WindowNo, this, "", "Generated Recipt: " + result.getDocumentNo() + 
							"\r\nBarcode: " + barcodetrx.getM_BarcodeTrx_ID());					
					enableHeader(true);
					resetValue();
					data.clear();
					loadTableOIS(data);					
				}
			}
			//			
		}else if(e.getActionCommand().equals(ConfirmPanel.A_CANCEL)){
			if (ADialog.ask(p_WindowNo, this,"Close","Are you sure?" )){
				dispose();
			}			
		}else{
			System.out.println("Barcode Scan.Other action: " +  e.getActionCommand());
		}
	}   //  actionPerformed
	
	private void resetValue(){
		barcodePN.setText("");
		infoInserted.setText(Msg.getMsg(Env.getCtx(), "NotFound"));
		isEceran.setSelected(false);
		isGenerated.setSelected(false);		
		totalLines=0;
		barcodetrx=null;
	}
	
	private String[] parseBarcode(String BarcodeText){
		BarcodeText=BarcodeText.trim();
		String [] result = new String[2];
		result[0]=BarcodeText.substring(0, lenUPC);
		result[1]=BarcodeText.substring(lenUPC);
		return result;
	}
	
	private String addBarcodeLine(String trxName) {
		// Get produk
		String[] barcode = parseBarcode(barcodePN.getText());
		/**if (!(barcode[1].equalsIgnoreCase(fullCode) || barcode[1].equalsIgnoreCase(retailCode))){
			return "Invalid barcode string";
		}**/
		infoInserted.setText("");
		String result = "";
		String sql = "SELECT M_Product_ID FROM M_Product WHERE UPC = ?";
		int M_Product_ID = 0;
		try {
			PreparedStatement pstmt = DB.prepareStatement(sql, trxName);
			pstmt.setString(1, barcode[0]);
			ResultSet rs = pstmt.executeQuery();
			if (rs.next())
				M_Product_ID = rs.getInt(1);
			rs.close();
			pstmt.close();
			if (M_Product_ID == 0)
				result = Msg.getMsg(Env.getCtx(), "not.found");
		} catch (SQLException e) {
			log.log(Level.SEVERE, sql.toString(), e);
			result = Msg.getMsg(Env.getCtx(), "not.found");
		}
		if (result.length() != 0)
			return result;

		MProduct prd = MProduct.get(Env.getCtx(), M_Product_ID);
		if (prd == null)
			return Msg.getMsg(Env.getCtx(), "not.found");		
		//
		//
		if (!confirmPanel.isOKVisible()) {
			barcodetrx = new MBarcodeTrx(Env.getCtx(), 0, trxName);
			barcodetrx.setC_DocType_ID((Integer) docTypeField.getValue());
			barcodetrx.setC_BPartner_ID((Integer) bPartnerField.getValue());
			barcodetrx.setIsSOTrx(false);
			barcodetrx.setScanDate(TimeUtil.getServerTime());
			barcodetrx.setM_Locator_ID((Integer) locatorField.getValue());
			barcodetrx.setIsGeneratedToInOut(false);		
			/**
			if (barcode[1].equalsIgnoreCase(fullCode)) {
				// Full code
				isEceran.setSelected(false);
				C_Uom_ID = Env.getContextAsInt(Env.getCtx(),
						"#Def_Package_UOM_ID");				
			} else if  (barcode[1].endsWith(retailCode)) { // retail
				isEceran.setSelected(true);
				C_Uom_ID = Env.getContextAsInt(Env.getCtx(),
					 	"#Def_Package_Inner_UOM_ID");
			}**/
			if (C_Uom_ID==0)
				return "Default UOM not set!";
			barcodetrx.setIsEceran(isEceran.isSelected());
			barcodetrx.save();
			UOM = MUOM.get(Env.getCtx(), C_Uom_ID).getUOMSymbol();
			enableHeader(false);
			//
		}
		String curCode= "";//(isEceran.isSelected()?retailCode:fullCode);
		if(!barcode[1].equalsIgnoreCase(curCode)){ //jika scan ganti tipe
			return "This transaction is for " + (isEceran.isSelected()?"Retail":"Full pack");
		}
		// Insert line
		//
		MBarcodeTrxLine barcodeLine = new MBarcodeTrxLine(Env.getCtx(), 0,
				barcodetrx.getM_BarcodeTrx_ID(), trxName);
		barcodeLine.setC_UOM_ID(C_Uom_ID);
		barcodeLine.setQty(Env.ONE); // Selalu 1
		barcodeLine.setM_Product_ID(M_Product_ID);
		barcodeLine.save();
		//
		//
		addData(barcode[0], M_Product_ID, prd.getName(), Env.ONE.doubleValue());
		infoInserted.setText(Msg.getMsg(Env.getCtx(), "Inserted"));
		return result;
	}

	private void enableHeader(boolean enabled){	
		locatorField.setReadWrite(enabled);
		bPartnerField.setReadWrite(enabled);
		docTypeField.setReadWrite(enabled);
		//
		confirmPanel.setOKVisible(!enabled);
		
	}
	/**
	 *  Table Model Listener.
	 *  - Recalculate Totals
	 *  @param e event
	 */
		
		
	private void addData(String PartNumber, int MProductID, String ProductName,
			double qty) {
		Vector<Object> line = new Vector<Object>(4);
		line.add(PartNumber); // 0-VendorProductNo
		KeyNamePair pp = new KeyNamePair(MProductID, ProductName);
		line.add(pp); // 1-Product
		line.add(qty); // 2-Qty
		pp = new KeyNamePair(C_Uom_ID, UOM);
		line.add(pp); // 3-UOM
		data.add(line);
		loadTableOIS(data);
		totalLines++;
	}
	
	
	protected void loadTableOIS(Vector<Vector<Object>> data) {
		//  Header Info
		    Vector<String> columnNames = new Vector<String>(4);
		    columnNames.add(Msg.getElement(Env.getCtx(), "VendorProductNo", false));
		    columnNames.add(Msg.translate(Env.getCtx(), "M_Product_ID"));		    
		    columnNames.add(Msg.translate(Env.getCtx(), "Quantity"));		    
		    columnNames.add("UOM");
		    
		    //  Remove previous listeners
		    //dataTable.getModel().removeTableModelListener(this);
		    //  Set Model
		    DefaultTableModel model = new DefaultTableModel(data, columnNames);
		    //model.addTableModelListener(this);
		    dataTable.setModel(model);
		    //		    
		    dataTable.setColumnClass(0, String.class, true);        //  1-VendorProductNo
		    dataTable.setColumnClass(1, String.class, true);        //  2-Product
		    dataTable.setColumnClass(2, Double.class, true);        //  3-Qty
		    dataTable.setColumnClass(3, String.class, true);        //  3-UOm
		    dataTable.autoSize();
		}
	
}


